package elitech.vietnam.weatherfashion.notification;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.text.Html;

import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.gson.Gson;

import elitech.vietnam.weatherfashion.MainActivity;
import elitech.vietnam.weatherfashion.R;
import elitech.vietnam.weatherfashion.WFApplication;
import elitech.vietnam.weatherfashion.config.Const;
import elitech.vietnam.weatherfashion.config.GlobalValue;
import elitech.vietnam.weatherfashion.dto.MemberDTO;
import elitech.vietnam.weatherfashion.dto.Notify;
import elitech.vietnam.weatherfashion.ultilities.ValueOption;

public class GCMIntentService extends IntentService {
	public static int NUMBER = 0;

	public static final String DATA_TAG = "json_data";
	public static final int NOTIFICATION_ID = 1;
	private NotificationManager mNotificationManager;
	NotificationCompat.Builder builder;
	
	private File cacheDir;

	public GCMIntentService() {
		super("GcmIntentService");
	}

	public static final String TAG = "GCM Demo";

	@Override
	protected void onHandleIntent(Intent intent) {
		Bundle extras = intent.getExtras();
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
		ValueOption option = GlobalValue.getInstance(getApplicationContext()).readOptionInfo();
		// The getMessageType() intent parameter must be the intent you received
		// in your BroadcastReceiver.
		String messageType = gcm.getMessageType(intent);

		if (!extras.isEmpty()) { // has effect of unparcelling Bundle
			/*
			 * Filter messages based on message type. Since it is likely that
			 * GCM will be extended in the future with new message types, just
			 * ignore any message types you're not interested in, or that you
			 * don't recognize.
			 */
			if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
				// sendNotification("Send error: " + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
				// sendNotification("Deleted messages on server: " +
				// extras.toString());
				// If it's a regular GCM message, do some work.
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
				// This loop represents the service doing some work.
				MemberDTO user = GlobalValue.getInstance(getApplicationContext()).readUserInfo();
				if (option.isGetNotification() && user != null) {
					String data = extras.getString("message");
					if (data != null && !data.equals("")) {
						Notify noti = new Gson().fromJson(data, Notify.class);
						noti.isNew = true;
						// Post notification of received message.
						if ((noti.Type == 1 && option.isType1) || (noti.Type == 2 && option.isType2) || (noti.Type == 3 && option.isType3) || (noti.Type == 4 && option.isType4))
							sendNotification(data, noti);
					}
				}
				// Log.i(TAG, "Received: " + extras.toString());
			}
		}
		// Release the wake lock provided by the WakefulBroadcastReceiver.
		GCMBroadcastReceiver.completeWakefulIntent(intent);
	}

	// Put the message into a notification and post it.
	// This is just one simple example of what you might choose to do with
	// a GCM message.
	private void sendNotification(String data, Notify noti) {
		WFApplication mContext = WFApplication.getInstance();
		
		cacheDir = getCacheDir();
		GCMEntity entity = GCMEntity.newInstance(mContext, noti);
		
		mContext.mListNoti.add(0, noti);

		mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);

		// PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
		// new Intent(this, MainActivity.class), 0);
		//
		// NotificationCompat.Builder mBuilder =
		// new NotificationCompat.Builder(this)
		// .setSmallIcon(R.drawable.ic_launcher)
		// .setLargeIcon(null)
		// .setContentTitle(noti.SenderName)
		// .setStyle(new NotificationCompat.BigTextStyle()
		// .bigText(noti.Content))
		// .setContentText(noti.Content);
		//
		// mBuilder.setContentIntent(contentIntent);
		// mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());

		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
		.setSmallIcon(entity.smallIcon)
		.setContentTitle(Html.fromHtml(entity.title))
		.setStyle(new NotificationCompat.BigTextStyle().bigText(entity.bigtext))
		.setContentText(entity.content);

		String url = entity.largeIcon;
		Bitmap bm = null;
		bm = readCache(url.replace("/", "").replace(".", "").replace(":", ""));
		if (bm == null) {
			try {
				InputStream in = new java.net.URL(url).openStream();
				bm = BitmapFactory.decodeStream(in);
				bm = Bitmap.createScaledBitmap(bm, 120, 120*bm.getHeight()/bm.getWidth(), false);
				writeCache(bm, url.replace("/", "").replace(".", "").replace(":", ""));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (bm == null) {
			bm = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
			bm = Bitmap.createScaledBitmap(bm, 120, 120*bm.getHeight()/bm.getWidth(), false);
		}
		
		mBuilder.setLargeIcon(bm);

		Intent resultIntent = new Intent(this, MainActivity.class);

		resultIntent.putExtra(DATA_TAG, data);

		resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

//		TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
//		// Adds the back stack for the Intent (but not the Intent itself)
//		stackBuilder.addParentStack(MainActivity.class);
//		// Adds the Intent that starts the Activity to the top of the stack
//		stackBuilder.addNextIntent(resultIntent);
//
//		PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
		PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
		mBuilder.setContentIntent(resultPendingIntent);

		ValueOption option = GlobalValue.getInstance(getApplicationContext()).readOptionInfo();
		if (option.isNotiSound) {
			Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
			mBuilder.setSound(alarmSound);
		}
		mBuilder.setAutoCancel(true);
		mBuilder.setNumber((NUMBER += 1));

		// ///////////////////////////////////
		NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

	// Sets a title for the Inbox style big view
		inboxStyle.setBigContentTitle(Html.fromHtml("<b>" + getString(R.string.app_name) + "</b>: " + NUMBER + getString(R.string.newmessages)));

		// Moves events into the big view
		for (int i = 0; i < mContext.mListNoti.size(); i++) {
			if (!mContext.mListNoti.get(i).isNew)
				continue;
			Notify noti1 = mContext.mListNoti.get(i);
			String str = (noti1.SenderName.equals("")) ? noti1.SenderUID : noti1.SenderName;
			if (noti1.Type == 1 || noti1.Type == 2) {
				str += ": " + noti1.Content;
			} else if (noti1.Type == 3)
				str += getString(R.string.uploadedanewstyle);
			else if (noti1.Type == 4)
				str += getString(R.string.addedyouasafriend);
			inboxStyle.addLine(str);
		}
		// Moves the big view style object into the notification object.
		mBuilder.setStyle(inboxStyle);
		// ////////////////////////

		// mId allows you to update the notification later on.
		mContext.mBadge.mListId.add(noti.Id);
		mContext.mBadge.increaseBadge();
		Intent intent = new Intent();
		intent.setAction(Const.ACTION_INCREASE_BADGE);
		mContext.sendBroadcast(intent);
		
		mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
	}

	public static class GCMEntity {
		String title, bigtext, content;
		String largeIcon;
		int smallIcon;

		static GCMEntity newInstance(Context context, Notify noti) {
			GCMEntity rs = new GCMEntity();
			rs.smallIcon = R.drawable.ic_launcher24;

			if (noti.Type == 1) {
				rs.title = "<b>";
				rs.title += (noti.SenderName.equals("")) ? noti.SenderUID : noti.SenderName;
				rs.title += "</b>" + context.getString(R.string.commentedonyourstyle);
				rs.bigtext = rs.title;
				rs.content = noti.Content;
				rs.largeIcon = Const.SERVER_IMAGE_URL + noti.Image;
			}
			if (noti.Type == 2) {
				rs.title = "<b>";
				rs.title += (noti.SenderName.equals("")) ? noti.SenderUID : noti.SenderName;
				rs.title += "</b>" + context.getString(R.string.alsoreplyonyourcomment);
				rs.bigtext = rs.title;
				rs.content = noti.Content;
				rs.largeIcon = Const.SERVER_IMAGE_URL + noti.Image;
			}
			if (noti.Type == 3) {
				rs.title = "<b>";
				rs.title += (noti.SenderName.equals("")) ? noti.SenderUID : noti.SenderName;
				rs.title += "</b>" + context.getString(R.string.uploadedanewstyle);
				rs.bigtext = rs.title;
				rs.content = noti.Content;
				rs.largeIcon = Const.SERVER_IMAGE_URL + noti.Image;
			}
			if (noti.Type == 4) {
				rs.title = "<b>";
				rs.title += (noti.SenderName.equals("")) ? noti.SenderUID : noti.SenderName;
				rs.title += "</b>" + context.getString(R.string.addedyouasafriend);
				rs.bigtext = rs.title;
				rs.content = "";
				rs.largeIcon = Const.SERVER_IMAGE_URL + noti.Image;
			}

			return rs;
		}
	}

	private Bitmap readCache(String Id) {
		File f = new File(cacheDir, Id);
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(f);
			return BitmapFactory.decodeStream(fis);
		} catch (FileNotFoundException e) {
			return null;
		}
	}

	private void writeCache(Bitmap photo, String Id) {
		File f = new File(cacheDir, Id);

		try {
			FileOutputStream out = new FileOutputStream(f);
			photo.compress(Bitmap.CompressFormat.JPEG, 100, out);
			out.flush();
			out.close();

		} catch (FileNotFoundException e) {} catch (IOException e) {}
	}

	public static void resetNumber() {
		NUMBER = 0;
	}
}
